package com.dili.dd.gpi.util;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author cdchenfolin
 */
@Component
public class DataServiceClient
{

    private static Logger logger = LoggerFactory.getLogger(DataServiceClient.class);
    private static final int CONNECT_TIME_OUT = 3000; // 连接超时时间3秒

    @Value("${serviceURL}")
    private String serviceUrl;

    @Value("${dmaServiceEnabled}")
    private boolean enabled;

    public DataServiceClient()
    {
    }

    public DataServiceClient(String serviceUrl)
    {
        this.serviceUrl = serviceUrl;
    }

    private String getResponse(String path)
    {
        String response;
        ClientConfig config = new DefaultClientConfig();
        Client client = Client.create(config);

        client.setConnectTimeout(CONNECT_TIME_OUT);
        WebResource webService = client.resource(UriBuilder.fromUri(serviceUrl).build());

        try
        {
            path = urlEncodePath(path);
            response = webService.path("rest").path(path).accept(MediaType.APPLICATION_JSON).post(String.class);
            logger.info("Call data service, path=" + path);
        }
        catch (Exception e)
        {
            logger.error("Call data service failed. path=" + path, e);
            response = "";
        }

        return StringUtils.isBlank(response) ? "" : response;
    }

    /**
     * 将path中的中文进行url编码
     *
     * @param path
     * @return
     */
    private String urlEncodePath(String path)
    {
        String[] strArray = path.split("/");
        String result = "";
        for (int i = 0; i < strArray.length; i++)
        {
            try
            {
                result += URLEncoder.encode(strArray[i], "utf-8") + "/";
            }
            catch (UnsupportedEncodingException e)
            {
                logger.error("path url encode error.", e);
            }
        }
        return result;
    }

    /**
     * 返回Java bean对象
     */
    public <T> T getResponseBean(String path, Class<T> t)
    {
        String jsonStr = getResponse(path);
        try
        {
            if (StringUtils.isEmpty(jsonStr))
            {
                return null;
            }
            return new ObjectMapper().readValue(jsonStr, t);
        }
        catch (JsonParseException e)
        {
            logger.error("json to bean failed.", e);
        }
        catch (JsonMappingException e)
        {
            logger.error("json to bean failed.", e);
        }
        catch (IOException e)
        {
            logger.error("json to bean failed.", e);
        }
        finally
        {

        }
        return null;
    }

    /**
     * 返回基本类型
     *
     * @param <T>
     * @param path
     * @param t
     * @return
     */
    public <T> T getBaseClassResponse(String path, Class<T> t)
    {
        String jsonStr;
        ClientConfig config = new DefaultClientConfig();
        Client client = Client.create(config);
        client.setConnectTimeout(CONNECT_TIME_OUT);
        WebResource webService = client.resource(UriBuilder.fromUri(serviceUrl).build());

        try
        {
            path = urlEncodePath(path);
            jsonStr = webService.path("rest").path(path).accept(MediaType.TEXT_PLAIN).post(String.class);
            logger.info("Call data service, path=" + path);
        }
        catch (Exception e)
        {
            logger.error("Call data service failed. path=" + path, e);
            jsonStr = "";
        }

        try
        {
            if (StringUtils.isEmpty(jsonStr))
            {
                return null;
            }
            return new ObjectMapper().readValue(jsonStr, t);
        }
        catch (JsonParseException e)
        {
            logger.error("json to base class failed.", e);
        }
        catch (JsonMappingException e)
        {
            logger.error("json to base class failed.", e);
        }
        catch (IOException e)
        {
            logger.error("json to base class failed.", e);
        }
        finally
        {

        }
        return null;
    }

    /**
     * 返回Java bean List
     *
     * @param <T>
     * @param path
     * @param t
     * @return
     */
    public <T> List<T> getResponseListBean(String path, Class<T> t)
    {
        String jsonArrayStr = getResponse(path);
        try
        {
            if (StringUtils.isEmpty(jsonArrayStr))
            {
                return null;
            }
            // return new ObjectMapper().readValue(jsonArrayStr, TypeFactory.collectionType(ArrayList.class, t));
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper
                    .readValue(jsonArrayStr, objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, t));
        }
        catch (JsonParseException e)
        {
            logger.error("json to bean failed.", e);
        }
        catch (JsonMappingException e)
        {
            logger.error("json to bean failed.", e);
        }
        catch (IOException e)
        {
            logger.error("json to bean failed.", e);
        }
        finally
        {

        }
        return null;

    }

    public <T> Map<String, T> getResponseMapBean(String path, Class<String> str, Class<T> t)
    {
        String jsonArrayStr = getResponse(path);
        if (StringUtils.isEmpty(jsonArrayStr))
        {
            return null;
        }
        try
        {
            // return new ObjectMapper().readValue(jsonArrayStr, TypeFactory.mapType(Map.class, str, t));
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(jsonArrayStr, objectMapper.getTypeFactory().constructMapLikeType(Map.class, str, t));

        }
        catch (JsonParseException e)
        {
            logger.error("json to bean failed.", e);
        }
        catch (JsonMappingException e)
        {
            logger.error("json to bean failed.", e);
        }
        catch (IOException e)
        {
            logger.error("json to bean failed.", e);
        }
        finally
        {

        }
        return null;

    }

    /**
     * 返回map
     *
     * @param <T>
     * @param path
     * @param str
     * @return
     */
    public <T> Map<String, List<T>> getResponseMapList(String path, Class<String> str)
    {
        String jsonArrayStr = getResponse(path);
        if (StringUtils.isEmpty(jsonArrayStr) || "[]".equals(jsonArrayStr))
        {
            return null;
        }
        try
        {
            // return new ObjectMapper().readValue(jsonArrayStr, TypeFactory.mapType(Map.class, str, t));
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(jsonArrayStr,
                    objectMapper.getTypeFactory().constructMapLikeType(Map.class, str, ArrayList.class));
        }
        catch (JsonParseException e)
        {
            logger.error("json to bean failed.", e);
        }
        catch (JsonMappingException e)
        {
            logger.error("json to bean failed.", e);
        }
        catch (IOException e)
        {
            logger.error("json to bean failed.", e);
        }
        finally
        {

        }
        return null;

    }

    /**
     * 向hbase插入用户应用信息
     *
     * @param userId
     * @param appkey
     */
    public String insertUserAppkey(String userId, String appkey)
    {
        String path = "manage/InsertUserAppKey/" + userId + "/" + appkey;
        return operateUserAppkey(path);
    }

    /**
     * 向hbase删除用户应用信息
     *
     * @param userId
     * @param appkey
     */
    public String deleteUserAppkey(String userId, String appkey)
    {
        String path = "manage/DeleteUserAppKey/" + userId + "/" + appkey;
        return operateUserAppkey(path);
    }

    /**
     * 插入或删除用户-appkey信息
     *
     * @param path
     * @return
     */
    private String operateUserAppkey(String path)
    {
        if (!enabled)
        {
            return "true";
        }

        String response;
        ClientConfig config = new DefaultClientConfig();
        Client client = Client.create(config);
        client.setConnectTimeout(CONNECT_TIME_OUT);
        WebResource webService = client.resource(UriBuilder.fromUri(serviceUrl).build());

        try
        {
            response = webService.path("rest").path(path).accept(MediaType.TEXT_PLAIN).post(String.class);
            logger.info("Call insert or delete user appkey data service, path=" + path);
        }
        catch (Exception e)
        {
            logger.error("Call insert or delete user appkey data service failed. path=" + path, e);
            response = "false";
        }

        return StringUtils.isBlank(response) ? "false" : response;
    }
}
